package org.mspring.platform.qiniu;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.mspring.platform.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.qiniu.api.auth.digest.Mac;
import com.qiniu.api.io.IoApi;
import com.qiniu.api.io.PutExtra;
import com.qiniu.api.io.PutRet;
import com.qiniu.api.net.CallRet;
import com.qiniu.api.rs.PutPolicy;
import com.qiniu.api.rs.RSClient;
import com.qiniu.api.rs.URLUtils;

/**
 * 七牛云储存
 *
 * @since 2014-05-07 15:00:07
 * @author Gao Youbo
 */
public class QiniuStorageService {

    private static final Logger log = LoggerFactory.getLogger(QiniuStorageService.class);

    private String accessKey;
    private String secretKey;
    /**
     * bucket
     */
    private String bucket;
    /**
     * bucket对应的域名
     */
    private String domain;

    /**
     * 上传文件
     *
     * 会根据文件自动生成一个key
     *
     * @param bucket
     * @param reader
     * @return
     * @throws Exception
     */
    public PutRet put(InputStream reader) throws Exception {
        byte[] bytes = IOUtils.toByteArray(reader);
        return put(bytes);
    }

    /**
     * 上传文件
     *
     * @param bytes
     * @return
     * @throws Exception
     */
    public PutRet put(byte[] bytes) throws Exception {
        String key = DigestUtils.md5Hex(bytes);
        return put(key, new ByteArrayInputStream(bytes));
    }

    /**
     *
     * @param key
     * @param bytes
     * @return
     * @throws Exception
     */
    public PutRet put(String key, byte[] bytes) throws Exception {
        InputStream reader = new ByteArrayInputStream(bytes);
        return put(key, reader);
    }

    /**
     * 上传文件
     *
     * @param key
     * @param reader
     * @return
     * @throws Exception
     */
    public PutRet put(String key, InputStream reader) throws Exception {
        Mac mac = new Mac(accessKey, secretKey);
        PutPolicy putPolicy = new PutPolicy(bucket);
        String uptoken = putPolicy.token(mac);
        PutExtra extra = new PutExtra();
        return IoApi.Put(uptoken, key, reader, extra);
    }

    /**
     * 删除文件
     *
     * @param key
     * @return
     */
    public CallRet delete(String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        Mac mac = new Mac(accessKey, secretKey);
        RSClient client = new RSClient(mac);
        return client.delete(bucket, key);
    }

    /**
     * 通过文件URL删除文件
     *
     * @param url
     * @return
     */
    public CallRet deleteByUrl(String url) {
        if (StringUtils.isBlank(url)) {
            return null;
        }
        String key = getKeyByUrl(url);
        if (StringUtils.isBlank(key)) {
            log.warn("无法通过URL获取文件KEY，URL={}", url);
            return null;
        }
        return delete(key);
    }

    public String getUrl(PutRet ret) throws EncoderException {
        if (ret != null && ret.ok()) {
            return getUrl(ret.getKey());
        }
        return null;
    }

    public String getUrl(String key) throws EncoderException {
        return URLUtils.makeBaseUrl(domain, key);
    }

    public String getKeyByUrl(String url) {
        String prefix = "http://" + domain + "/";
        String temp = StringUtils.substringAfter(url, prefix);
        if (StringUtils.contains(temp, "?")) {
            return StringUtils.substringBefore(temp, "?");
        }
        if (StringUtils.contains(temp, QiniuImageStyleUtils.DEFAULT_SPLIT)) {
            return StringUtils.substringBefore(temp, QiniuImageStyleUtils.DEFAULT_SPLIT);
        }
        return temp;
    }

    public String getAccessKey() {
        return accessKey;
    }

    public void setAccessKey(String accessKey) {
        this.accessKey = accessKey;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public String getBucket() {
        return bucket;
    }

    public void setBucket(String bucket) {
        this.bucket = bucket;
    }

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }
}
